<style lang="less">
.red {
    background-color: #ffe9e9;
}
</style>
<template>
    <div>
        <p>[转自] https://my.oschina.net/daoxiaozhang/blog/3063427</p>
        <p>输入数独题，按钮计算得</p>
        <table v-if="loading">
            <tr v-for="trItem, trI in testData">
                <td v-for="tdItem, tdI in trItem">
                    <input :class="tdItem==''?'red':''"
                           :value="tdItem==''?'':tdItem"
                           @change="(event)=>{change(event, trI, tdI)}" />
                </td>
            </tr>
        </table>
        <y-button @click="handelClick">计算</y-button>
    </div>
</template>
<script>
export default {
    name: 'sudoku',
    data() {
        return {
            loading: true,
            testData: [
                ['5', '3', '', '', '7', '', '', '', ''],
                ['6', '', '', '1', '9', '5', '', '', ''],
                ['', '9', '8', '', '', '', '', '6', ''],
                ['8', '', '', '', '6', '', '', '', '3'],
                ['4', '', '', '8', '', '3', '', '', '1'],
                ['7', '', '', '', '2', '', '', '', '6'],
                ['', '6', '', '', '', '', '2', '8', ''],
                ['', '', '', '4', '1', '9', '', '', '5'],
                ['', '', '', '', '8', '', '', '7', '9']
            ]
        }
    },
    created() {

    },
    methods: {
        change(event, trI, tdI) {
            console.log(event, trI, tdI);
            this.$set(this.testData[trI], tdI, event.target.value);
        },
        handelClick() {
            console.time();

            this.loading = false;

            this.solveSudoku(this.testData);
            this.loading = true;
        },
        getNext(board) {
            var result = null;
            for (let i = 0; i < 9; i++) {
                if (!result) {
                    for (let j = 0; j < 9; j++) {
                        if (board[i][j] == '' && !result) {
                            result = {
                                x: i,
                                y: j
                            };
                        }
                    }
                }
            }
            return result
        },
        check(board, row, col, k) {
            let result = true;
            if (board[row].find(item => item == k)) {
                result = false
            }
            for (var i = 0; i < 9; i++) {
                if (board[i][col] == k) {
                    result = false;
                }
            }
            let _areai = Math.floor(row / 3) * 3
            let _areaj = Math.floor(col / 3) * 3
            for (let _i = 0; _i < 3; _i++) {
                for (let _j = 0; _j < 3; _j++) {
                    if (board[_areai + _i][_areaj + _j] == k) {
                        result = false;
                    }
                }
            }
            return result;
        },
        solveSudoku(board) {
            let next = this.getNext(board);
            if (!next) {
                return 'success'
            } else {
                let {
                    x,
                    y
                } = next;
                for (var k = 1; k < 10; k++) {
                    if (this.check(board, x, y, k + '')) {
                        board[x][y] = k + '';
                        let flag = this.solveSudoku(board);
                        if (flag == 'success') {
                            console.log(board);
                console.timeEnd();

                        } else if (flag == 'error') {
                            board[x][y] = ''
                        }
                    }
                }
                if (board[x][y] == '') {
                    return 'error'
                }
            }
        }
    }
}
</script>
